home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 2.toast / pc / sample code / quicktime / quicktimeintro / play movie / common files / macframework.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  24.8 KB  |  938 lines

  1. //////////
  2. //
  3. //    File:        MacFramework.c
  4. //
  5. //    Contains:    Code for the QuickTime sample code framework that is specific to the Macintosh. 
  6. //                This code handles windows, menus, events, and other low-level things. Put your
  7. //                application-specific code into the file ComApplication.c. 
  8. //
  9. //    Written by:    Tim Monroe
  10. //                Based on the QTShell code written by Tim Monroe, which in turn was based on the MovieShell
  11. //                code written by Apple DTS (Kent Sandvik). This current version is now very far removed from
  12. //                MovieShell.
  13. //
  14. //    Copyright:    © 1999 by Apple Computer, Inc., all rights reserved.
  15. //
  16. //    Change History (most recent first):
  17. //
  18. //       <10>         03/02/00    rtm        made changes to get things running under CarbonLib
  19. //       <9>         01/14/00    rtm        reworked window-dragging and -updating code to support graphics files
  20. //       <8>         12/23/99    rtm        tweaked mouseDown handling in QTFrame_StandardModalDialogEventFilter
  21. //       <7>         12/16/99    rtm        added gMouseClickTime global variable and code to set it in mouseUp
  22. //                                    case in QTFrame_HandleEvent
  23. //       <6>         12/12/99    rtm        tweaked inDrag handling in QTFrame_HandleEvent
  24. //       <5>         11/30/99    rtm        option-click in close box now closes all open movie windows (per HIG)
  25. //       <4>         11/29/99    rtm        reworked QTFrame_DestroyMovieWindow to use NavAskSaveChanges
  26. //       <3>         11/16/99    rtm        factored QTFrame_HandleEvent out of QTFrame_MainEventLoop, so we can
  27. //                                    handle events from other code, if necessary
  28. //       <2>         11/11/99    rtm        made some preliminary changes for Carbon; still some work to be done
  29. //       <1>         11/05/99    rtm        first file; based on earlier sample code
  30. //       
  31. //////////
  32.  
  33. //////////
  34. //
  35. // header files
  36. //
  37. //////////
  38.  
  39. #include "MacFramework.h"
  40. #include "PMUtilities.h"
  41.  
  42.  
  43. //////////
  44. //
  45. // global variables
  46. //
  47. //////////
  48.  
  49. Boolean             gShuttingDown = false;                // are we shutting down?
  50. Boolean                gAppInForeground;                    // is our application in the foreground?    
  51. Boolean                gHasNewDialogCalls;                    // are the new Dialog Manager functions available?
  52.  
  53. Str255                 gWindowTitle = kDefaultWindowTitle;    // default name for created windows
  54. Rect                 gWindowRect = kDefaultWindowRect;    // default rectangle for created windows
  55. GrowZoneUPP            gAppGrowZoneUPP;                    // UPP to our grow zone callback
  56. ModalFilterUPP        gModalFilterUPP;                    // UPP to our custom dialog event filter
  57. UserItemUPP            gUserItemProcUPP;                    // UPP to our custom dialog user item procedure
  58. Handle                gEmergencyMemory;                    // handle to our emergency memory reserve
  59.  
  60. short                 gAppResFile = kInvalidFileRefNum;    // file reference number for this application's resource file
  61. FSSpec                gAppFSSpec;                            // file specification for the application itself
  62. Str255                gAppName;                            // the name of this application
  63.  
  64. long                gMouseClickTime;                    // for double-click calculation
  65. extern OSType         *gValidFileTypes;                    // the list of file types that our application can open
  66.  
  67.  
  68. //////////
  69. //
  70. // main
  71. // The main function for this application.
  72. //
  73. // Set up the application's execution environment; make sure QuickTime (etc.) is installed,
  74. // then start handling events.
  75. //
  76. //////////
  77.  
  78. void main (void)
  79. {
  80.     OSErr        myErr = noErr;
  81.     
  82.     QTFrame_InitMacEnvironment(10L);
  83.     
  84. #ifdef TARGET_OS_MAC    
  85.     // make sure that QuickTime is available and that we can initialize it
  86.     if (!IsQuickTimeInstalled()) {
  87.         QTFrame_ShowWarning("\pQuickTime is not installed on this computer. Exiting.", 0);
  88.         ExitToShell();
  89.     }
  90.  
  91. #ifdef TARGET_CPU_PPC
  92.     if (!IsQuickTimeCFMInstalled()) {
  93.         QTFrame_ShowWarning("\pThe QuickTime PowerPlug extension is not installed on this computer. Exiting.", 0);
  94.         ExitToShell();
  95.     }
  96. #endif 
  97. #endif
  98.  
  99.     DoInitQuickTime();
  100.  
  101.     // do any application-specific initialization
  102.     QTApp_Init(kInitAppPhase_BothPhases);
  103.  
  104.     // get and process events until the user quits
  105.     QTFrame_MainEventLoop();
  106.     
  107.     ExitMovies();
  108.     ExitToShell();
  109. }
  110.  
  111.  
  112. //////////
  113. //
  114. // QTFrame_InitMacEnvironment
  115. // Initialize the Macintosh runtime environment.
  116. //
  117. //////////
  118.  
  119. static void QTFrame_InitMacEnvironment (long theNumMoreMasters)
  120. {
  121. #if TARGET_API_MAC_CARBON
  122. #pragma unused(theNumMoreMasters)
  123. #endif
  124.  
  125.     short            myVRefNum;
  126.     long            myDirID;
  127.  
  128. #if !TARGET_API_MAC_CARBON    
  129.     long            myIndex;
  130.  
  131.     // add more space to the stack
  132.     SetApplLimit((Ptr)(GetApplLimit() - kExtraStackSpaceSize));
  133.             
  134.     // expand heap zone to its limit
  135.     MaxApplZone();
  136.     
  137.     // allocate some additional master pointer blocks
  138.     for (myIndex = 0; myIndex < theNumMoreMasters; myIndex++)
  139.         MoreMasters();
  140.  
  141.     InitGraf(&qd.thePort);
  142.     InitFonts();
  143.     InitWindows();
  144.     InitMenus();
  145.     TEInit();
  146.     InitDialogs(NULL);
  147. #endif
  148.     InitCursor();
  149.  
  150.     // initialize and install the menu bar
  151.     QTFrame_InitMenuBar();
  152.  
  153. #if !TARGET_API_MAC_CARBON
  154.     // install a grow zone procedure to handle low memory situations
  155.     gEmergencyMemory = NewHandle(kEmergencyMemorySize);
  156.     if (gEmergencyMemory != NULL) {
  157.         gAppGrowZoneUPP = NewGrowZoneProc(QTFrame_GrowZoneProcedure);
  158.         SetGrowZone(gAppGrowZoneUPP);
  159.     }
  160. #endif
  161.     
  162.     // initialize foreground/background state
  163.     gAppInForeground = true;
  164.  
  165.     // see whether the new Dialog Manager functions are available
  166. #if TARGET_API_MAC_CARBON
  167.     gHasNewDialogCalls = true;
  168. #else
  169.     gHasNewDialogCalls = QTUtils_TrapAvailable(_DialogDispatch);
  170. #endif
  171.         
  172.     // create modal dialog filter and user item UPPs
  173.     gModalFilterUPP = NewModalFilterProc(QTFrame_StandardModalDialogEventFilter);
  174.     gUserItemProcUPP = NewUserItemProc(QTFrame_StandardUserItemProcedure);
  175.  
  176.     // get the application's resource file
  177.     gAppResFile = CurResFile();
  178.     
  179.     // get the application's name from the resource file
  180.     GetIndString(gAppName, kAppNameResID, kAppNameResIndex);
  181.     
  182.     // get the application's location and save it in gAppFSSpec
  183.     HGetVol(NULL, &myVRefNum, &myDirID);
  184.     FSMakeFSSpec(myVRefNum, myDirID, gAppName, &gAppFSSpec);
  185. }
  186.  
  187.  
  188. //////////
  189. //
  190. // QTFrame_GrowZoneProcedure
  191. // A grow zone procedure. This is straight out of IM: Memory (pp. 1-46ff)
  192. //
  193. //////////
  194.  
  195. PASCAL_RTN long QTFrame_GrowZoneProcedure (Size theBytesNeeded)
  196. {
  197. #pragma unused(theBytesNeeded)
  198.  
  199.     long        myA5;
  200.     Size        myBytesFreed;
  201.     
  202.     // get current A5; we might get called at a time that A5 isn't valid
  203.     myA5 = SetCurrentA5();
  204.     
  205.     if ((*gEmergencyMemory != NULL) && (gEmergencyMemory != GZSaveHnd())) {
  206.         EmptyHandle(gEmergencyMemory);
  207.         myBytesFreed = kEmergencyMemorySize;
  208.     } else {
  209.         myBytesFreed = 0;                        // no more memory to release    
  210.     }    
  211.         
  212.     myA5 = SetA5(myA5);
  213.     
  214.     return(myBytesFreed);
  215. }
  216.  
  217.  
  218. //////////
  219. //
  220. // QTFrame_InitMenuBar
  221. // Set up the menu bar. This is straight out of IM: Macintosh Toolbox Essentials (pp. 3-50ff)
  222. //
  223. //////////
  224.  
  225. static Boolean QTFrame_InitMenuBar (void)
  226. {
  227.     Handle        myMenuBar = NULL;
  228.     long        myResponse;
  229.     OSErr        myErr = noErr;
  230.  
  231.     myMenuBar = GetNewMBar(kMenuBarResID);
  232.  
  233. #if TARGET_API_MAC_CARBON    
  234.     // to get the theme-savvy menu bar, we need to call RegisterAppearanceClient.
  235.     RegisterAppearanceClient();
  236. #endif
  237.  
  238.     if (myMenuBar == NULL)
  239.         return(false);
  240.     
  241.     SetMenuBar(myMenuBar);                                    // install the menus
  242.     DisposeHandle(myMenuBar);
  243.     
  244.     // see whether we are running under MacOS X;
  245.     // if so, remove the Quit menu item and its preceding separator line
  246.     myErr = Gestalt(gestaltSystemVersion, &myResponse);
  247.     if (myErr == noErr)
  248.         if (myResponse >= 0x00000A00) {
  249.             DeleteMenuItem(GetMenuHandle(kFileMenuResID), MENU_ITEM(IDM_EXIT));
  250.             DeleteMenuItem(GetMenuHandle(kFileMenuResID), MENU_ITEM(IDM_EXIT) - 1);    // the separator line
  251.         }
  252.         
  253. #if !TARGET_API_MAC_CARBON    
  254.     AppendResMenu(GetMenuHandle(kAppleMenuResID), 'DRVR');    // add desk accessory names to Apple menu
  255. #endif
  256.     QTFrame_AdjustMenus(NULL, NULL);
  257.     DrawMenuBar();
  258.     
  259.     return(true);
  260. }
  261.  
  262.  
  263. //////////
  264. //
  265. // QTFrame_MainEventLoop
  266. // Retrieve and process events.
  267. //
  268. //////////
  269.  
  270. static void QTFrame_MainEventLoop (void)
  271. {
  272.     EventRecord                myEvent;
  273.     Boolean                    isEventHandled;
  274.     
  275.     while (!gShuttingDown) {
  276. #if !TARGET_API_MAC_CARBON    
  277.         // make sure we've still got our memory reserve; reallocate it if it's been used
  278.         if ((gEmergencyMemory == NULL) || (*gEmergencyMemory == NULL))
  279.             ReallocateHandle(gEmergencyMemory, kEmergencyMemorySize);
  280. #endif
  281.     
  282.         WaitNextEvent(everyEvent, &myEvent, kWNEDefaultSleep, NULL);
  283.         
  284.         // first, perform any application-specific event loop actions
  285.         isEventHandled = QTApp_HandleEvent(&myEvent);
  286.             
  287.         // then, if this event hasn't been handled, let all movie controllers have access to the event
  288.         if (!isEventHandled)
  289.             isEventHandled = QTFrame_CheckMovieControllers(&myEvent);
  290.  
  291.         // then, if this event hasn't been handled, handle it ourselves
  292.         if (!isEventHandled)
  293.             QTFrame_HandleEvent(&myEvent);
  294.         
  295.     } // while (!gShuttingDown)
  296. }
  297.  
  298.  
  299. //////////
  300. //
  301. // QTFrame_MainEventLoop
  302. // Retrieve and process events.
  303. //
  304. //////////
  305.  
  306. void QTFrame_HandleEvent (EventRecord *theEvent)
  307. {
  308.     WindowPtr                myWindow = NULL;
  309.     WindowObject             myWindowObject = NULL;
  310.     short                    myWindowPart;
  311.     Rect                    myScreenRect;
  312.     Rect                    myRefreshArea;
  313.  
  314.     myWindow = FrontWindow();
  315.  
  316.     switch (theEvent->what) {
  317.         case mouseUp:
  318.             gMouseClickTime = TickCount();        // for double-click calculation
  319.             break;
  320.  
  321.         case mouseDown:
  322.         
  323.             myWindowPart = FindWindow(theEvent->where, &myWindow);
  324.  
  325.             // menu bar and window-related events:            
  326.             switch (myWindowPart) {
  327.                 case inSysWindow:
  328. #if !TARGET_API_MAC_CARBON
  329.                     // a mouse click in a window belonging to a desk accessory
  330.                     SystemClick(theEvent, myWindow);
  331. #endif
  332.                     break;
  333.                     
  334.                 case inMenuBar:
  335.                     // a mouse click in the menu bar
  336.                     QTFrame_AdjustMenus(FrontWindow(), NULL);
  337.                     QTFrame_HandleMenuCommand(MenuSelect(theEvent->where));
  338.                     break;
  339.                     
  340.                 case inDrag: {
  341.                     Rect                 myRect;
  342.                     
  343.                     myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow);
  344.                     if (myWindowObject != NULL) {
  345.                         
  346.                         if ((**myWindowObject).fMovie != NULL)
  347.                             GetMovieBox((**myWindowObject).fMovie, &myRect);
  348.                         
  349.                         if ((**myWindowObject).fGraphicsImporter != NULL)
  350.                             GraphicsImportGetNaturalBounds((**myWindowObject).fGraphicsImporter, &myRect);
  351.                         
  352.                         GetRegionBounds(GetGrayRgn(), &myScreenRect);
  353.                         DragAlignedWindow(myWindow, theEvent->where, &myScreenRect, &myRect, NULL);
  354.  
  355.                     } else {
  356.                         GetRegionBounds(GetGrayRgn(), &myScreenRect);
  357.                         DragWindow(myWindow, theEvent->where, &myScreenRect);
  358.                     }
  359.                     
  360.                     break;                            
  361.                 }
  362.                     
  363.                 case inContent:
  364.                     if (myWindow != FrontWindow()) {
  365.                         SelectWindow(myWindow);
  366.                         MacSetPort((GrafPtr)GetWindowPort(myWindow));
  367.                     } else {
  368.                         QTApp_HandleContentClick(myWindow, theEvent);
  369.                     }
  370.                     
  371.                     break;
  372.                 
  373.                 case inGoAway:
  374.                     if (TrackGoAway(myWindow, theEvent->where)) {
  375.                         // if the option key is down, close all open movie windows; otherwise, close just the frontmost
  376.                         if (theEvent->modifiers & optionKey)
  377.                             QTFrame_CloseMovieWindows();
  378.                         else
  379.                             QTFrame_DestroyMovieWindow(myWindow);
  380.                     }
  381.                     break;
  382.             } // end switch(myWindowPart)
  383.             break;
  384.  
  385.         // system-level events:
  386.         case updateEvt:
  387.             myWindow = (WindowReference)theEvent->message;
  388.             if (myWindow != NULL) {
  389.                 RgnHandle        myVisRegion;
  390.                 
  391.                 // draw an image file
  392.                 myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow);
  393.                 if (myWindowObject != NULL)
  394.                     if ((**myWindowObject).fGraphicsImporter != NULL)
  395.                         GraphicsImportDraw((**myWindowObject).fGraphicsImporter);
  396.                 
  397.                 myVisRegion = NewRgn();
  398.                 GetPortVisibleRegion(GetWindowPort(myWindow), myVisRegion);
  399.                 GetRegionBounds(myVisRegion, &myRefreshArea);
  400.                 
  401.                 QTApp_Draw(myWindow, &myRefreshArea);
  402.                 DisposeRgn(myVisRegion);
  403.             }
  404.             break;
  405.             
  406.         case keyDown:
  407.         case autoKey:
  408.             QTFrame_HandleKeyPress(theEvent);
  409.             break;
  410.         
  411.         case diskEvt: {
  412. #if !TARGET_API_MAC_CARBON
  413.             Point            myPoint = {100, 100};
  414.         
  415.             if (HiWord(theEvent->message) != noErr)
  416.                 (void)DIBadMount(myPoint, theEvent->message);
  417. #endif
  418.             break;
  419.         }
  420.         
  421.         case activateEvt:
  422.             myWindow = (WindowReference)theEvent->message;
  423.             
  424.              if (QTFrame_IsAppWindow(myWindow))
  425.                 QTFrame_ActivateController(myWindow, ((theEvent->modifiers & activeFlag) != 0 ));
  426.             break;
  427.             
  428.         case osEvt:
  429.             switch ((theEvent->message >> 24) & 0x00ff) {        // get high byte of message
  430.                 case suspendResumeMessage:
  431.                 
  432.                     // set the foreground/background state
  433.                     gAppInForeground = (theEvent->message & resumeFlag) != 0;
  434.                     
  435.                     // activate the front window, if there is one    
  436.                     if (myWindow != NULL)
  437.                         QTFrame_ActivateController(myWindow, gAppInForeground);
  438.                     break;
  439.                 
  440.                 case mouseMovedMessage:
  441.                     break;
  442.             }
  443.             break;
  444.         
  445.         case kHighLevelEvent:
  446.             AEProcessAppleEvent(theEvent);
  447.             break;
  448.             
  449.         case nullEvent:
  450.             // do idle-time processing for all open movie windows
  451.             myWindow = QTFrame_GetFrontMovieWindow();
  452.             while (myWindow != NULL) {
  453.                 if (gAppInForeground) {
  454.                     QTApp_Idle(myWindow);
  455.                 } else {
  456.                     WindowObject myWindowObject = QTFrame_GetWindowObjectFromWindow(myWindow);
  457.                     if (myWindowObject != NULL) {
  458.                         Movie myMovie = (**myWindowObject).fMovie;
  459.                         if (myMovie)
  460.                             MoviesTask(myMovie, DoTheRightThing);
  461.                     }
  462.                 }
  463.                     
  464.                 myWindow = QTFrame_GetNextMovieWindow(myWindow);
  465.             }
  466.             break;
  467.     } // switch (theEvent->what)
  468. }
  469.         
  470.  
  471. //////////
  472. //
  473. // QTFrame_HandleMenuCommand
  474. // Handle a menu selection.
  475. //
  476. //////////
  477.  
  478. void QTFrame_HandleMenuCommand (long theMenuResult)
  479. {
  480.     short        myMenuID, myMenuItem;
  481.     Cursor        myArrow;
  482.     
  483.     MacSetCursor(GetQDGlobalsArrow(&myArrow));
  484.  
  485.     myMenuID = HiWord(theMenuResult);
  486.     myMenuItem = LoWord(theMenuResult);
  487.     
  488.     switch (myMenuID) {
  489.     
  490.         case kAppleMenuResID:
  491.             switch (myMenuItem) {
  492.                 case kAboutMenuItem:        // About box
  493.                     QTFrame_ShowAboutBox();     
  494.                     break;
  495.                 
  496.                 default:                     // Apple menu handling
  497. #if !TARGET_API_MAC_CARBON
  498.                     {
  499.                         Str255        myDAName;
  500.                         
  501.                         GetMenuItemText(GetMenuHandle(kAppleMenuResID), myMenuItem, myDAName);
  502.                         (void)OpenDeskAcc(myDAName);
  503.                     }
  504. #endif
  505.                     break;
  506.             }
  507.             break;
  508.  
  509.         case kFileMenuResID:
  510.             QTFrame_HandleFileMenuItem(QTFrame_GetFrontMovieWindow(), MENU_IDENTIFIER(myMenuID, myMenuItem));
  511.             break;
  512.     
  513.         case kEditMenuResID:
  514.             QTFrame_HandleEditMenuItem(QTFrame_GetFrontMovieWindow(), MENU_IDENTIFIER(myMenuID, myMenuItem));
  515.             break;
  516.  
  517.         default:
  518.             // do any application-specific menu handling
  519.             QTApp_HandleMenu(MENU_IDENTIFIER(myMenuID, myMenuItem));
  520.             break;
  521.         
  522.     } // switch (myMenuID)
  523.     
  524.     HiliteMenu(0);
  525. }
  526.  
  527.  
  528. //////////
  529. //
  530. // QTFrame_HandleKeyPress
  531. // Handle key presses. This is modelled on Inside Macintosh: Macintosh Toolbox Essentials, p. 3-78.
  532. //
  533. //////////
  534.  
  535. void QTFrame_HandleKeyPress (EventRecord *theEvent)
  536. {
  537.     char        myKey;
  538.     
  539.     myKey = theEvent->message & charCodeMask;
  540.     
  541.     if (theEvent->modifiers & cmdKey) {
  542.         // if the command key is down, it must be a keyboard shortcut for a menu selection;
  543.         // adjust the menus and find the menu command that the shortcut picks out
  544.         QTFrame_AdjustMenus(FrontWindow(), NULL);
  545.         QTFrame_HandleMenuCommand(MenuKey(myKey));
  546.     } else {
  547.         // otherwise, we'll assume it's meant for our application
  548.         QTApp_HandleKeyPress(myKey);
  549.     }
  550. }
  551.  
  552.  
  553. //////////
  554. //
  555. // QTFrame_QuitFramework
  556. // Do any framework-specific shut-down.
  557. //
  558. //////////
  559.  
  560. void QTFrame_QuitFramework (void)
  561. {
  562.     // set our global flag to indicate we're shutting down
  563.     gShuttingDown = true;
  564.     
  565.     // do application-specific processing that must occur before movie windows are closed
  566.     QTApp_Stop(kStopAppPhase_BeforeDestroyWindows);
  567.     
  568.     // close all open movie windows; note that the user can cancel the shutting down
  569.     QTFrame_CloseMovieWindows();
  570.         
  571.     // test the quit flag; a call to QTFrame_DestroyMovieWindow may have reset it
  572.     if (!gShuttingDown)
  573.         return;
  574.     
  575.     // do application-specific processing that must occur after movie windows are closed
  576.     QTApp_Stop(kStopAppPhase_AfterDestroyWindows);
  577.  
  578.     // release our list of valid file types
  579.     if (gValidFileTypes != NULL)
  580.         DisposePtr((Ptr)gValidFileTypes);
  581.  
  582. #if !TARGET_API_MAC_CARBON    
  583.     // release the grow zone memory
  584.     DisposeHandle(gEmergencyMemory);
  585. #endif
  586.     
  587.     // release any routine descriptors
  588.     DisposeGrowZoneUPP(gAppGrowZoneUPP);
  589.     DisposeModalFilterUPP(gModalFilterUPP);
  590.     DisposeUserItemUPP(gUserItemProcUPP);    
  591. }
  592.  
  593.  
  594. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  595. //
  596. // Framework utilities.
  597. //
  598. // The framework uses the following functions to create movies and handle dialog boxes. You probably won't
  599. // need to use them directly.
  600. //
  601. ///////////////////////////////////////////////////////////////////////////////////////////////////////////
  602.  
  603. //////////
  604. //
  605. // QTFrame_CreateMovieWindow
  606. // Create a new window to display the movie in.
  607. //
  608. //////////
  609.  
  610. WindowReference QTFrame_CreateMovieWindow (void)
  611. {
  612.     WindowReference            myWindow = NULL;
  613.     WindowObject            myWindowObject = NULL;
  614.     
  615.     // create a new window to display the movie in
  616.     myWindow = NewCWindow(NULL,
  617.                             &gWindowRect,
  618.                             gWindowTitle,
  619.                             false,
  620.                             noGrowDocProc,
  621.                             (WindowPtr)-1L,
  622.                             true,
  623.                             0);
  624.  
  625.     // create a new window object associated with the new window
  626.     QTFrame_CreateWindowObject(myWindow);
  627.  
  628.     return(myWindow);
  629. }
  630.  
  631.  
  632. //////////
  633. //
  634. // QTFrame_DestroyMovieWindow
  635. // Close the specified movie window.
  636. //
  637. //////////
  638.  
  639. void QTFrame_DestroyMovieWindow (WindowReference theWindow)
  640. {
  641.     WindowObject        myWindowObject = NULL;
  642.     OSErr                myErr = noErr;
  643.     
  644.     // get the window object associated with the specified window
  645.     myWindowObject = QTFrame_GetWindowObjectFromWindow(theWindow);
  646.     if (myWindowObject == NULL) {
  647.         // if the window passed in isn't a movie window, just dispose of it and return
  648.         if (theWindow != NULL) {
  649.             DisposeWindow(theWindow);
  650.             theWindow = NULL;
  651.         }
  652.         return;
  653.     }
  654.     
  655.     // if the window's data is "dirty", give the user a chance to save it
  656.     if ((**myWindowObject).fIsDirty) {
  657.         Str255                        myString;
  658.         NavAskSaveChangesAction        myAction;
  659.         NavAskSaveChangesResult        myResult;
  660.         NavDialogOptions            myDialogOptions;
  661.         NavEventUPP                    myEventUPP = NewNavEventProc(QTFrame_HandleNavEvent);
  662.  
  663.         // get the title of the window
  664.         GetWTitle(theWindow, myString);
  665.         
  666.         // install the application and document names
  667.         NavGetDefaultDialogOptions(&myDialogOptions);
  668.         BlockMoveData(gAppName, myDialogOptions.clientName, gAppName[0] + 1);
  669.         BlockMoveData(myString, myDialogOptions.savedFileName, myString[0] + 1);
  670.         
  671.         // specify the action
  672.         myAction = gShuttingDown ? kNavSaveChangesQuittingApplication : kNavSaveChangesClosingDocument;
  673.         
  674.         // display the "Save changes" dialog box
  675.         myErr = NavAskSaveChanges(&myDialogOptions, myAction, &myResult, myEventUPP, NULL);
  676.         if (myErr != noErr)
  677.             myResult = kNavAskSaveChangesCancel;
  678.             
  679.         switch (myResult) {
  680.             case kNavAskSaveChangesSave:
  681.                 // save the data in the window
  682.                 QTFrame_UpdateMovieFile(theWindow);
  683.                 break;
  684.                 
  685.             case kNavAskSaveChangesCancel:
  686.                 // do not close the window, and do not quit the application
  687.                 gShuttingDown = false;
  688.                 return;
  689.                 
  690.             case kNavAskSaveChangesDontSave:
  691.                 // discard any unsaved changes (that is, don't do anything)
  692.                 break;
  693.         }
  694.  
  695.         DisposeNavEventUPP(myEventUPP);
  696.     }
  697.  
  698.     // if we got to this point, it's okay to close and destroy the window
  699.     QTFrame_CloseWindowObject(myWindowObject);
  700.  
  701.     DisposeWindow(theWindow);
  702. }
  703.  
  704.  
  705. //////////
  706. //
  707. // QTFrame_StandardUserItemProcedure
  708. // A standard user-item procedure to outline the OK button in a modal dialog.
  709. //
  710. //////////
  711.  
  712. PASCAL_RTN void QTFrame_StandardUserItemProcedure (DialogPtr theDialog, short theItem)
  713. {
  714. #pragma unused(theItem)
  715.  
  716.     short                myItemKind;            // for GetDialogItem
  717.     Handle                myItemHandle;        // for GetDialogItem
  718.     Rect                myItemRect;            // for GetDialogItem
  719.  
  720.     if (!gHasNewDialogCalls) {        // no need to do any of this if the new Dialog Manager calls are available
  721.         GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect);        
  722.         MacInsetRect(&myItemRect, -4, -4);
  723.         PenSize(3, 3);
  724.         FrameRoundRect(&myItemRect, 16, 16);
  725.         PenSize(1, 1);
  726.     }
  727. }
  728.  
  729.  
  730. //////////
  731. //
  732. // QTFrame_StandardModalDialogEventFilter
  733. // A standard modal dialog event filter. 
  734. //
  735. //////////
  736.  
  737. PASCAL_RTN Boolean QTFrame_StandardModalDialogEventFilter (DialogPtr theDialog, EventRecord *theEvent, short *theItemHit)
  738. {
  739.     Boolean                myEventHandled = false;
  740.     short                myItemKind;            // for GetDialogItem
  741.     Handle                myItemHandle;        // for GetDialogItem
  742.     Rect                myItemRect;            // for GetDialogItem
  743.     unsigned long        myTicks;            // for Delay
  744.     char                myKey;        
  745.     WindowReference        myWindow = NULL;
  746.     short                myPart;    
  747.     OSErr                myErr = noErr;
  748.         
  749.     switch (theEvent->what) {
  750.         case updateEvt:
  751.             // update the specified window, if it's behind the modal dialog box
  752.             myWindow = (WindowReference)theEvent->message;
  753.             if ((myWindow != NULL) && (myWindow != GetDialogWindow(theDialog))) {
  754.                 QTFrame_HandleEvent(theEvent);
  755.                 myEventHandled = false;        // so sayeth IM
  756.             }
  757.             break;
  758.  
  759.         case nullEvent:
  760.             // do idle-time processing for all open windows in our window list
  761.             if (gAppInForeground) 
  762.                 QTFrame_IdleMovieWindows();
  763.  
  764.             myEventHandled = false;
  765.             break;
  766.             
  767.         case keyDown:
  768.         case autoKey:
  769.             // if new Dialog Manager calls are NOT available, handle certain key presses
  770.             if (!gHasNewDialogCalls) {
  771.                 // first, map Command-period to Escape key...
  772.                 myKey = theEvent->message & charCodeMask;
  773.                 if (theEvent->modifiers & cmdKey)
  774.                     if (myKey == kPeriod)
  775.                         myKey = kEscapeKey;
  776.                         
  777.                 // ...then, handle the standard keyboard equivalents of OK and Cancel buttons
  778.                 switch (myKey) {
  779.                     case kReturnKey:
  780.                     case kEnterKey:
  781.                         *theItemHit = kStdOkItemIndex;
  782.                         GetDialogItem(theDialog, kStdOkItemIndex, &myItemKind, &myItemHandle, &myItemRect);
  783.                         HiliteControl((ControlHandle)myItemHandle, kControlButtonPart);
  784.                         Delay(kMyButtonDelay, &myTicks);
  785.                         HiliteControl((ControlHandle)myItemHandle, kControlNoPart);
  786.                         myEventHandled = true;
  787.                         break;
  788.                     case kEscapeKey:
  789.                         *theItemHit = kStdCancelItemIndex;
  790.                         GetDialogItem(theDialog, kStdCancelItemIndex, &myItemKind, &myItemHandle, &myItemRect);
  791.                         HiliteControl((ControlHandle)myItemHandle, kControlButtonPart);
  792.                         Delay(kMyButtonDelay, &myTicks);
  793.                         HiliteControl((ControlHandle)myItemHandle, kControlNoPart);
  794.                         myEventHandled = true;
  795.                         break;
  796.                     default:
  797.                         break;
  798.                 }
  799.             }
  800.             break;
  801.             
  802.         case mouseDown:
  803.             myPart = FindWindow(theEvent->where, &myWindow);
  804.             if ((myPart == inDrag) && (myWindow == GetDialogWindow(theDialog))) {
  805.                 Rect        myScreenRect;
  806.                 
  807.                 GetRegionBounds(GetGrayRgn(), &myScreenRect);
  808.                 DragWindow(myWindow, theEvent->where, &myScreenRect);
  809.                 myEventHandled = true;
  810.             }
  811.             break;
  812.             
  813.         default:
  814.             myEventHandled = false;
  815.             break;
  816.     }    
  817.     
  818.     // let the OS's standard filter proc handle the event, if it hasn't already been handled
  819.     if (gHasNewDialogCalls && (myEventHandled == false))
  820.         myEventHandled = StdFilterProc(theDialog, theEvent, theItemHit);
  821.     
  822.     return(myEventHandled);
  823. }
  824.  
  825.  
  826. //////////
  827. //
  828. // QTFrame_CheckMovieControllers
  829. // Let all movie controllers have a chance to process the event.
  830. //
  831. // Returns true if the event was handled by some movie controller, false otherwise
  832. //
  833. //////////
  834.  
  835. static Boolean QTFrame_CheckMovieControllers (EventRecord *theEvent)
  836. {    
  837.     WindowPtr                myWindow = NULL;
  838.     MovieController            myMC = NULL;
  839.     
  840.     myWindow = QTFrame_GetFrontMovieWindow();
  841.     while (myWindow != NULL) {
  842.         myMC = QTFrame_GetMCFromWindow(myWindow);
  843.         if (myMC != NULL)
  844.             if (MCIsPlayerEvent(myMC, theEvent))
  845.                 return(true);
  846.         
  847.         myWindow = QTFrame_GetNextMovieWindow(myWindow);
  848.     }
  849.     
  850.     return(false);
  851. }
  852.  
  853.  
  854. //////////
  855. //
  856. // QTFrame_ShowAboutBox
  857. // Display and manage the About dialog box.
  858. //
  859. //////////
  860.  
  861. void QTFrame_ShowAboutBox (void)
  862. {
  863.     DialogPtr            myDialog = NULL;
  864.     short                 myItem;
  865.     short                 mySavedResFile;
  866.     GrafPtr                mySavedPort;
  867.     short                myItemKind;
  868.     Handle                myItemHandle;
  869.     Rect                myItemRect;
  870.     
  871.     // get the current resource file and port
  872.     mySavedResFile = CurResFile();
  873.     GetPort(&mySavedPort);
  874.     
  875.     // set the application's resource file;
  876.     // otherwise, we'd get the dialog's resources from the current resource file,
  877.     // which might not be the correct one....
  878.     UseResFile(gAppResFile);
  879.     
  880.     // deactivate any frontmost movie window
  881.     QTFrame_ActivateController(QTFrame_GetFrontMovieWindow(), false);
  882.     
  883.     myDialog = GetNewDialog(kAboutBoxID, NULL, (WindowPtr)-1L);
  884.     if (myDialog == NULL)
  885.         goto bail;
  886.         
  887.     SetPortDialogPort(myDialog);
  888.         
  889.     if (gHasNewDialogCalls)
  890.         SetDialogDefaultItem(myDialog, kStdOkItemIndex);
  891.     
  892.     // make sure that the OK button is outlined in bold, even if new Dialog Manager calls not available
  893.     GetDialogItem(myDialog, kOKButtonUserItem, &myItemKind, &myItemHandle, &myItemRect);
  894.     SetDialogItem(myDialog, kOKButtonUserItem, myItemKind, (Handle)gUserItemProcUPP, &myItemRect);
  895.  
  896.     // display and handle events in the dialog box until the user clicks OK
  897.     do {
  898.         ModalDialog(gModalFilterUPP, &myItem);
  899.     } while (myItem != kStdOkItemIndex);
  900.     
  901. bail:
  902.     // restore the previous resource file and port
  903.     MacSetPort(mySavedPort);
  904.     UseResFile(mySavedResFile);
  905.     
  906.     if (myDialog != NULL)
  907.         DisposeDialog(myDialog);
  908. }
  909.  
  910.  
  911. //////////
  912. //
  913. // QTFrame_ShowWarning
  914. // Display a warning box.
  915. //
  916. //////////
  917.  
  918. void QTFrame_ShowWarning (Str255 theMessage, OSErr theErr)
  919. {
  920.     Str255                myString;
  921.     short                 mySavedResFile;
  922.     
  923.     // get the current resource file and set the application's resource file
  924.     mySavedResFile = CurResFile();
  925.     UseResFile(gAppResFile);
  926.  
  927.     // insert argument into the message text template, to get the message text
  928.     NumToString(theErr, myString);
  929.     ParamText("\pWarning!", theMessage, theErr ? myString: NULL, NULL);
  930.  
  931.     // display the dialog box
  932.     Alert(kAlertErrorID, gModalFilterUPP);
  933.     
  934.     // restore the original resource file
  935.     UseResFile(mySavedResFile);
  936. }
  937.  
  938.